# -*- coding: utf-8 -*-
import json
import time
import os
import hashlib
import logging
import yaml

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S'
                    )

# 遍历文件夹->如果有Done->校验每个文件->输出到Done中->留下all verified


WORKINGDIR = \
    CONFIG_NAME = \
    DONE_NAME =\
    VERIFY_NAME =\
    MD5_NAME = \
    GRUBIGNORE_NAME = ''


def md5sum(filename):
    """md5sum实现."""
    digest = hashlib.md5()
    with open(filename, 'rb') as f:
        while True:
            chunk = f.read(8096)
            if not chunk:
                break
            digest.update(chunk)
    return digest.hexdigest()


def verify_this(dirname):
    """校验某个文件夹."""
    logging.info('start to verify : ' + dirname)
    verifyset = set(os.listdir(dirname))
    verifyset -= set([CONFIG_NAME, DONE_NAME, VERIFY_NAME, MD5_NAME])
    logging.info(verifyset)
    with open(os.path.join(dirname, MD5_NAME))as file:
        md5list = json.load(file)
    res = {}
    flag = 1
    for filename in verifyset:
        digest = md5sum(os.path.join(dirname, filename))
        if digest in md5list:
            res[filename] = 'verified'
        else:
            flag = 0
            res[filename] = 'unverified'
    if flag:
        with open(os.path.join(dirname, VERIFY_NAME), 'w') as file:
            json.dump(res, file)
            file.writelines('\nverified : ' + time.ctime())
        logging.info('successfully verified!')
    else:
        with open(os.path.join(dirname, DONE_NAME), 'w') as file:
            json.dump(res, file)
            file.writelines('\nverified : ' + time.ctime())


def verify():
    """检查所有目录的md5,只有完全匹配才会贴上verified标记."""
    os.chdir(WORKINGDIR)
    dirlist = os.listdir(WORKINGDIR)
    # 跳过IGNORELIST
    IGNORELIST = set()
    if os.path.isfile(GRUBIGNORE_NAME):
        with open(GRUBIGNORE_NAME) as file:
            IGNORELIST = set(json.load(file))
    havebeenverified = 0
    verifylist = []
    for dir in dirlist:
        if os.path.isdir(dir):
            if os.path.exists(os.path.join(dir, DONE_NAME)):
                if os.path.exists(os.path.join(dir, VERIFY_NAME)):
                    havebeenverified += 1
                    logging.info(dir + ' have already been verified, skip!')
                else:
                    if not dir in IGNORELIST:
                        verifylist.append(dir)
            else:
                logging.warning(
                    dir + ' haven\'t pull yet , call puller fisrt!')
        else:
            logging.info(dir + ' is not a dir , jump!')
    length_of_verifylist = len(verifylist)

    logging.info('total : ' + length_of_verifylist + ' to verify')
    global_count = 0
    for dir in verifylist:
        try:
            verify_this(dir)
        except:
            logging.warning('some error happened,' + 'failed to verify ' + dir)
        else:
            global_count += 1
    logging.info('finish verify with ' + str(global_count) +
                 ' to ' + length_of_verifylist)
    logging.info(str(global_count) +
                 str(havebeenverified) + 'verified in total')


def init(config_file):
    """init,must use before any function."""
    global WORKINGDIR, GRUBIGNORE_NAME, CONFIG_NAME, MD5_NAME, DONE_NAME, VERIFY_NAME
    with open(config_file) as file:
        dic = yaml.load(file.read())
    WORKINGDIR = dic['WORKINGDIR']
    GRUBIGNORE_NAME = dic['GRUBIGNORE_NAME']
    CONFIG_NAME = dic['CONFIG_NAME']
    MD5_NAME = dic['MD5_NAME']
    DONE_NAME = dic['DONE_NAME']
    VERIFY_NAME = dic['VERIFY_NAME']
    return config_file



if __name__ == "__main__":
    init('conf.json')
    verify()
